<?php

namespace api\modules\backend\models;

use yii\base\Model;
use common\library\FFmpeg;

class UploadForm extends Model
{
    public $targetFileType;
    public $zipFileNumber = 0;
    public $file;
    public $prefix;
    public $unZipTargetArray = [];

    public $uploadFile;

    public function rules()
    {
        return [
            [['uploadFile'], 'file', 'maxFiles' => 10, 'extensions' => 'png,jpg,doc,docx,pdf,xls,xlsx,ppt,pptx,zip,mp4'],
        ];
    }

    /**
     * 設置儲存文件類型
     * @param $type
     */
    public function setTargetFileType($type)
    {
        $this->targetFileType = $type;
    }

    /**
     * 獲取上傳文件後綴名
     * @param $type
     * @return string
     */
    public function getUploadFileExtension($type)
    {
        switch ($type) {
            case in_array($type, ['application/x-zip', 'application/zip', 'application/x-zip-compressed']):
                $ext = '.zip';
                break;
            case 'image/jpeg':
                $ext = '.jpg';
                break;
            case 'image/png':
                $ext = '.png';
                break;
            case 'image/jpg':
                $ext = '.jpg';
                break;
            case 'video/mp4':
                $ext = '.mp4';
                break;
            default:
                $ext = '';
        }

        return $ext;
    }

    /**
     * 獲取Zip內的文件後綴名
     * @param $type
     * @return string
     */
    public function getZipExtension($type)
    {
        switch ($type) {
            case 'jpeg':
                $ext = '.jpg';
                break;
            case 'png':
                $ext = '.png';
                break;
            case 'jpg':
                $ext = '.jpg';
                break;
            case 'mp4':
                $ext = '.mp4';
                break;
            default:
                $ext = '';
        }

        return $ext;
    }

    /**
     * 匹配文件类型
     * @param $extension
     * @return bool
     */
    public function matchType($extension)
    {
        switch ($this->targetFileType) {
            case 'image':
                $match = in_array($extension, ['png', 'jpg', 'jpeg']);
                break;
            case 'video':
                $match = in_array($extension, ['mp4']);
                break;
            default:
                $match = false;
        }

        return $match;
    }

    /**
     * 生成随机名
     * @param int $length
     * @return bool|string
     */
    function generateRandomName($length = 8)
    {
        $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
        str_shuffle($chars);
        $str = time() . substr(str_shuffle($chars), 26, $length);

        return $str;
    }

    /**
     * 压缩包内文件重命名
     * @param $zipFile
     */
    public function zipRename($zipFile)
    {
        $this->prefix = [];

        $zip = new \ZipArchive();

        if ($zip->open($zipFile) === TRUE) {

            $this->zipFileNumber = $zip->numFiles;

            for ($i = 0; $i < $this->zipFileNumber; $i++) {
                $extension = pathinfo($zip->getNameIndex($i), PATHINFO_EXTENSION);

                if (!preg_match('/[\x{4e00}-\x{9fa5}]/u', $zip->getNameIndex($i)) > 0 && $this->matchType($extension)) {
                    if (!isset($this->prefix[$zip->getNameIndex($i)[0]])) $this->prefix[] = $zip->getNameIndex($i)[0];

                    $extension = pathinfo($zip->getNameIndex($i), PATHINFO_EXTENSION);
                    $newFilename = $this->generateRandomName() . $this->getZipExtension($extension);

                    $zip->renameName($zip->getNameIndex($i), $newFilename);
                    $this->unZipTargetArray[] = $newFilename;
                }
            }

            $zip->close();
        }
    }

    /**
     * 生成图片
     * @param $thumbArr
     * @param $savePath
     * @param string $ext
     * @return array
     */
    public function generateImage($thumbArr, $savePath, $ext = 'png')
    {
        $ffmpeg = new FFmpeg();

        $result = [];
        foreach ($thumbArr as $key => $resources) {
            $output = $ffmpeg->getVideoInfo($resources['path']);
            $width = $output['streams'][1]['width'];
            $height = $output['streams'][1]['height'];
            $thumb_path = $savePath . '/' . $this->generateRandomName(16) . '.' . $ext;

            $ffmpeg->generateImage($resources['path'], $thumb_path, $width, $height);

            $result[] = array(
                'filename' => $resources['filename'],
                'thumb_path' => $thumb_path,
                'video_path' => $resources['path'],
                'width' => $width,
                'height' => $height
            );
        }

        return $result;
    }

    /**
     * 解压zip
     * @param $zipFile
     * @param $folder
     * @return array
     */
    function unZip($zipFile, $folder)
    {
        $fileArray = [];
        $this->zipRename($zipFile);

        $zip = new \ZipArchive();

        if ($zip->open($zipFile) === TRUE) {

            $zip->extractTo($folder, $this->unZipTargetArray);

            for ($i = 0; $i < $this->zipFileNumber; $i++) {
                $extension = pathinfo($zip->getNameIndex($i), PATHINFO_EXTENSION);

                if (!preg_match('/[\x{4e00}-\x{9fa5}]/u', $zip->getNameIndex($i)) > 0 && $this->matchType($extension)) {
                    $fileArray[] = [
                        'filename' => $zip->getNameIndex($i),
                        'path' => $folder . '/' . $zip->getNameIndex($i)
                    ];
                }
            }

            $zip->close();
        }

        @unlink($zipFile);

        return !empty($fileArray) && $this->targetFileType === 'video' ? $this->generateImage($fileArray, $folder) : $fileArray;
    }

    /**
     * 文件是否存在
     * @param $uploadPath
     * @param $folder
     * @return string
     */
    public function fileExists($uploadPath, $folder)
    {
        $folderArr = explode('/', $folder);
        foreach ($folderArr as $key => $value) {
            $uploadPath = $uploadPath . '/' . $value;
            if (!file_exists($uploadPath)) {
                mkdir($uploadPath);
            }
        }

        return $uploadPath;
    }

    public function getPrefix()
    {
        return $this->prefix;
    }
}
